/**
 *    Copyright 2009-2020 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.plugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author Clinton Begin
 */
public class InterceptorChain {

  private final List<Interceptor> interceptors = new ArrayList<>();

  /**
   * 这个是mybatis的插件执行的地方，mybatis有几个地方会执行这个插件呢？
   * 从源码里面我们可以知道插件执行的地方有：
   * 1.创建执行器的时候：Configuration.newExecutor方法；
   * 2.创建参数处理器的时候：Configuration.newParameterHandler方法；
   * 3.创建sql处理声明的时候：Configuration.newStatementHandler方法；
   * 4.创建处理结果集的时候：Configuration.newResultSetHandler方法。
   * 所以说我们编写的插件可以从这几个地方去做拦截
   *    * 当在上面的4中情况的执行过程中，会来根据目标的类，比如创建的4大接口的过程中会来调用，
   *    * 如果目标类上在插件中满足拦截的条件，就会返回一个代理对象，而当最终在调用这4大接口的方法过程中
   *    * 如果调用的方法满足拦截的条件，会调用这里的invoke方法，也就是代理调用了
   * @param target
   * @return
   */
  public Object pluginAll(Object target) {
    //获取所有的拦截器，执行拦截器的方法
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

  public void addInterceptor(Interceptor interceptor) {
    interceptors.add(interceptor);
  }

  public List<Interceptor> getInterceptors() {
    return Collections.unmodifiableList(interceptors);
  }

}
